home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
17 Bit Software 5: The Fifth Dimension
/
17 Bit - The Fifth Dimension (1995)(17 Bit Software)[!].iso
/
files
/
3728.dms
/
3728.adf
/
XPKDisk
/
xdclear.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-08
|
14KB
|
625 lines
/*
* On a clear disk you can seek forever...
*
* Clear out all unused blocks on a disk, and if a whole track is
* unused, delete the appropriate track file.
*
* $Id: xdclear.c,v 1.3 1995/04/08 20:23:48 Rhialto Exp $
* $Log: xdclear.c,v $
* Revision 1.3 1995/04/08 20:23:48 Rhialto
* Add/correct version strings.
*
* Revision 1.2 1995/04/02 14:58:51 Rhialto
* Take LowCyl into account. This fixes partitions that don't start at cyl 0.
* Change ETD_* commands to TD_* because the A4000's scsi.device does not
* understand them.
* Fix bogus exit status.
*
* Revision 1.1 1993/11/08 13:23:03 Rhialto
* Initial revision
*
* (C) Copyright 1993,1995 by Olaf 'Rhialto' Seibert. All rights reserved.
*/
#include "xpkdisk.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos/dos.h>
#include <dos/filehandler.h>
extern struct DosLibrary *DOSBase;
extern struct ExecBase *SysBase;
static const char idString[] = "\0$VER: xdClear " STR(VERSION) "." STR(REVISION) "\r\n";
static const char rcsId[] = "$Id: xdclear.c,v 1.3 1995/04/08 20:23:48 Rhialto Exp $";
struct FileSysStartupMsg Fssm;
struct DosEnvec De;
struct IOExtTD *Io;
struct MsgPort *Port;
struct MsgPort *HandlerPort;
ULONG NumTracks;
ULONG MaxKey;
ULONG RootBlockKey;
ULONG *RootBlock;
ULONG BitsPerBitmapBlock;
ULONG BMBlocksPerBitmapExtBlock;
ULONG BitmapBlockNr = -2;
ULONG *BitmapBlock;
ULONG BitmapExtBlockNr = -1;
ULONG *BitmapExtBlock;
ULONG *ZeroBlock;
ULONG LowTrack;
ULONG Offset;
int XpkDisk;
int Pretend;
int Verbose;
int SectorsCleared;
int SectorsReallyCleared;
int TracksDeleted;
int TracksReallyDeleted;
#define debug(x) printf x
#define debug0(x)
#define SIZE De.de_SizeBlock
#define BM_BLOCKS_PER_ROOTBLOCK ((-25)-(-49)+1)
#define BM_BLOCKS_PER_BMEBLOCK (SIZE - 1)
int
GetKey(ULONG key, ULONG *buffer)
{
long offset = Offset + sizeof(ULONG) * SIZE * key;
Io->iotd_Req.io_Command = CMD_READ; /* ETD */
Io->iotd_Req.io_Offset = offset;
Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
Io->iotd_Req.io_Data = (char *)buffer;
if (DoIO((struct IORequest *)Io)) {
printf("Read error %d on sector %d (offset 0x%lx bytes, %dK, %dM)!\n",
Io->iotd_Req.io_Error, key, offset, offset / 1024, offset / (1024 * 1024));
if (Verbose) {
printf("device=\"%s\" unit %d\n", Fssm.fssm_Device, Fssm.fssm_Unit);
}
return Io->iotd_Req.io_Error;
}
return 0;
}
int
PutKey(ULONG key, ULONG *buffer)
{
Io->iotd_Req.io_Command = CMD_WRITE; /* ETD */
Io->iotd_Req.io_Offset = Offset + sizeof(ULONG) * SIZE * key;
Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
Io->iotd_Req.io_Data = (char *)buffer;
if (DoIO((struct IORequest *)Io)) {
printf("Write error %d on sector %d!\n",
Io->iotd_Req.io_Error, key);
return Io->iotd_Req.io_Error;
}
return 0;
}
/*
* All checksums make the block add to 0.
*/
int
CheckSum(ULONG *buffer)
{
int i;
ULONG sum = 0;
for (i = SIZE; i > 0; i--)
sum += *buffer++;
return sum? 0 : 1;
}
int
GetBitmapExtBlock(ULONG blocknr)
{
if (blocknr != BitmapExtBlockNr) {
ULONG key;
ULONG keynr;
if (blocknr < BitmapExtBlockNr || BitmapExtBlockNr == (ULONG)-1) {
key = RootBlock[SIZE - 24];
keynr = 0;
if (Verbose >= 2)
printf("GetBitmapExtBlock %d -> first key %d\n", blocknr, key);
} else {
key = BitmapExtBlock[SIZE - 1];
keynr = BitmapExtBlockNr + 1;
if (Verbose >= 2)
printf("GetBitmapExtBlock %d -> next key %d\n", blocknr, key);
}
while (key && keynr <= blocknr) {
GetKey(key, BitmapExtBlock);
BitmapExtBlockNr = keynr;
if (Verbose >= 2)
printf("GetBitmapExtBlock %d -> get %d key %d\n",
blocknr, keynr, key);
key = BitmapExtBlock[SIZE - 1];
keynr++;
}
if (key == 0 && BitmapExtBlockNr != blocknr) {
debug0(("No bitmap extension block #%d!!!\n", keynr));
return -97;
}
}
return 0;
}
int
GetBitmapBlock(ULONG blocknr, ULONG *buffer)
{
ULONG key;
if (blocknr < BM_BLOCKS_PER_ROOTBLOCK) {
key = RootBlock[SIZE - 49 + blocknr];
if (Verbose >= 2)
printf("GetBitmapBlock %d -> root key %d\n", blocknr, key);
} else {
ULONG tmp = blocknr - BM_BLOCKS_PER_ROOTBLOCK;
ULONG bmeblocknr = tmp / BM_BLOCKS_PER_BMEBLOCK;
ULONG offset = tmp % BM_BLOCKS_PER_BMEBLOCK;
if (Verbose >= 2)
printf("GetBitmapBlock %d -> extension block %d\n", blocknr, bmeblocknr);
if ((tmp = GetBitmapExtBlock(bmeblocknr)) == 0)
key = BitmapExtBlock[offset];
else
return tmp;
if (Verbose >= 2)
printf("GetBitmapBlock %d -> (ext'd) key %d\n", blocknr, key);
}
if (key == 0) {
debug0(("Key for BitmapBlock #%d is 0.\n", blocknr));
return -98;
}
if (GetKey(key, buffer) == 0) {
if (CheckSum(buffer) == 0) {
printf("Checksum of Bitmap Block #%d, key %d is bad!\n",
blocknr, key);
return -99;
}
return 0;
}
return Io->iotd_Req.io_Error;
}
int
GetBit(ULONG key)
{
ULONG blocknr;
key -= De.de_Reserved;
blocknr = key / BitsPerBitmapBlock;
if (blocknr != BitmapBlockNr) {
if (Verbose >= 2)
printf("GetBit %d -> BitmapBlock %d\n", key+De.de_Reserved, blocknr);
if (blocknr == BitmapBlockNr + 1)
memcpy(BitmapBlock + 1, BitmapBlock + SIZE, (SIZE - 1) * 4);
else
GetBitmapBlock(blocknr, BitmapBlock);
if (GetBitmapBlock(blocknr + 1, BitmapBlock + SIZE) == 0) {
memmove(BitmapBlock + SIZE, BitmapBlock + SIZE + 1, (SIZE - 1) * 4);
} else {
memset(BitmapBlock + SIZE, 0, SIZE * 4);
debug0(("Zeroed 2nd bitmapblock.\n"));
}
BitmapBlockNr = blocknr;
}
return key % BitsPerBitmapBlock; /* bit offset */
}
void
ZeroOut(int key)
{
debug0(("ZeroOut %d.\n", key));
SectorsCleared++;
if (GetKey(key, ZeroBlock) == 0) {
int i;
ULONG *p;
for (i = SIZE, p = ZeroBlock; i > 0; i--, p++) {
if (*p != 0) {
for (; i > 0; i--, p++)
*p = 0;
if (!Pretend)
PutKey(key, ZeroBlock);
SectorsReallyCleared++;
break;
}
}
}
}
void
ZeroTrack(int track)
{
char name[64];
ULONG i;
TracksDeleted++;
i = sprintf(name, XPKDISKDIR "Unit%lx/", Fssm.fssm_Unit);
NewName(&name[i], LowTrack + track);
if (i = Lock(name, SHARED_LOCK)) {
UnLock(i);
TracksReallyDeleted++;
printf("Delete %s.\n", name);
if (!Pretend)
DeleteFile(name);
}
}
LONG
min(LONG a, LONG b)
{
return a < b? a: b;
}
void
CheckBits(int bitoffset, int numbits, ULONG key, int track)
{
int longindex;
int longoffset;
int bits;
ULONG *p;
char ones = 0;
char zeros = 0;
ULONG mask;
int pass;
ULONG mykey;
if (Verbose >= 1) {
printf(" Track %5d... ", track);
}
if (key == De.de_Reserved) {
/* Pretend the reserved sectors are in use */
zeros = 1;
}
for (pass = 0 + !XpkDisk; pass < 2; pass++) {
longindex = bitoffset / 32;
longoffset = bitoffset % 32;
bits = numbits;
mykey = key;
p = BitmapBlock + 1 + longindex;
mask = 1L << longoffset;
debug0(("Start %08lx, track %d, pass %d, mask %08lx, bits %d\n",
*p, track, pass, mask, bits));
while (bits > 0) {
if (*p == 0xFFFFFFFF) {
if (pass > 0) {
int i = min(32-1-longoffset, bits-1);
debug0(("bits %d, *p %x, mykey %d: ", bits, *p, mykey));
for (; i >= 0; i--) {
ZeroOut(mykey + i);
}
}
bits -= 32 - longoffset;
mask = 1;
mykey += 32 - longoffset;
longoffset = 0;
p++;
debug0(("Next %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
ones = 1;
} else if (*p == 0) {
bits -= 32 - longoffset;
mask = 1;
mykey += 32 - longoffset;
longoffset = 0;
p++;
debug0(("Next %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
zeros = 1;
} else {
if (*p & mask) {
/* Block free */
ones = 1;
if (pass > 0) {
debug0(("%08lx ", *p));
ZeroOut(mykey);
}
} else {
/* Block in use */
zeros = 1;
}
bits--;
mask <<= 1;
mykey++;
if (mask == 0) {
longoffset = 0;
mask = 1;
p++;
debug0(("Next %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
}
}
}
if (!ones || !zeros)
break;
}
if (Verbose) {
printf("%c\r", ones ? 'Z' : ' ');
fflush(stdout);
}
if (XpkDisk && !zeros)
ZeroTrack(track);
}
void
Clear(void)
{
ULONG key;
ULONG nextkey;
ULONG track;
/* First, test the boot block for file system type */
GetKey(0, RootBlock);
if ((RootBlock[0] & 0xFFFFFF00) != 'DOS\0') {
printf("Not an AmigaDOS disk.\n");
return;
}
/* Start at rootblock */
GetKey(RootBlockKey, RootBlock);
if (RootBlock[0] != 2 || RootBlock[SIZE-1] != ST_ROOT) {
printf("Rootblock is not a root block.\n");
return;
}
if (!CheckSum(RootBlock)) {
printf("Rootblock checksum bad.\n");
return;
}
if (RootBlock[SIZE - 50] == 0) {
printf("Bitmap valid flag not set.\n");
return;
}
key = De.de_Reserved;
track = key / De.de_BlocksPerTrack;
nextkey = (track + 1) * De.de_BlocksPerTrack;
if (Verbose >= 1) {
printf("This disk has %d tracks.\n", NumTracks);
}
CheckBits(GetBit(key), nextkey - key, key, track);
track++;
key = nextkey;
for (; key < MaxKey; key = nextkey, track++) {
int offset;
nextkey = key + De.de_BlocksPerTrack;
offset = GetBit(key);
CheckBits(offset, De.de_BlocksPerTrack, key, track);
chkabort();
}
}
int
OpenAll(char *devicename)
{
int fail = 0;
{
struct DosList *dl;
if (dl = LockDosList(LDF_DEVICES | LDF_READ)) {
if (dl = FindDosEntry(dl, devicename, LDF_DEVICES)) {
struct FileSysStartupMsg *fssm;
struct DosEnvec *de;
fssm = BADDR(dl->dol_misc.dol_handler.dol_Startup);
de = BADDR(fssm->fssm_Environ);
Fssm = *fssm;
Fssm.fssm_Device = (BSTR)((char *)BADDR(Fssm.fssm_Device) + 1);
De = *de;
HandlerPort = dl->dol_Task;
} else {
printf("No %s.\n", devicename);
fail = 1;
}
UnLockDosList(LDF_DEVICES | LDF_READ);
} else {
printf("Can't LockDosList.\n");
fail = 2;
}
}
if (fail != 0)
return fail;
if (HandlerPort) {
DoPkt(HandlerPort, ACTION_FLUSH, 0, 0, 0, 0, 0);
DoPkt(HandlerPort, ACTION_INHIBIT, -1, 0, 0, 0, 0);
}
if (De.de_TableSize < DE_BUFMEMTYPE)
De.de_BufMemType = MEMF_CHIP | MEMF_PUBLIC;
Port = CreateMsgPort();
if (Port == NULL)
return 3;
Io = (struct IOExtTD *)CreateExtIO(Port, sizeof(*Io));
if (Io == NULL)
return 4;
if (fail = OpenDevice((char *)Fssm.fssm_Device, Fssm.fssm_Unit,
(struct IORequest *)Io, Fssm.fssm_Flags)) {
printf("Can't OpenDevice %s unit %d, error %d.\n",
Fssm.fssm_Device, Fssm.fssm_Unit, fail);
return 5;
}
Io->iotd_Req.io_Command = TD_CHANGENUM;
fail = DoIO((struct IORequest *)Io);
if (fail) {
printf("TD_CHANGENUM: error %d\n", fail);
return 5;
}
Io->iotd_Count = Io->iotd_Req.io_Actual;
XpkDisk = strcmp(FilePart((char *)Fssm.fssm_Device), "xpkdisk.device") == 0;
RootBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
if (RootBlock == NULL)
return 6;
BitmapBlock = AllocMem(2 * SIZE * sizeof(ULONG), De.de_BufMemType);
if (BitmapBlock == NULL)
return 7;
BitmapExtBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
if (BitmapExtBlock == NULL)
return 8;
ZeroBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
if (ZeroBlock == NULL)
return 9;
LowTrack = De.de_Surfaces * De.de_LowCyl;
Offset = sizeof(ULONG) * SIZE * De.de_BlocksPerTrack * LowTrack;
NumTracks = De.de_Surfaces * (De.de_HighCyl - De.de_LowCyl + 1);
MaxKey = De.de_BlocksPerTrack * NumTracks;
RootBlockKey = (MaxKey - 1 + De.de_Reserved) / 2;
BitsPerBitmapBlock = 32 * (SIZE - 1);
debug0(("Offset %x, RootBlockKey %d\n", Offset, RootBlockKey));
debug0(("Bits/BitmapBlock %d\n", BitsPerBitmapBlock));
if (De.de_BlocksPerTrack > BitsPerBitmapBlock) {
printf(
"What a funny disk you have! %d blocks/track is more than I can handle!\n",
De.de_BlocksPerTrack);
return 10;
}
return 0;
}
void
CloseAll(void)
{
if (RootBlock)
FreeMem(RootBlock, SIZE * sizeof(unsigned long));
if (BitmapBlock)
FreeMem(BitmapBlock, 2 * SIZE * sizeof(unsigned long));
if (BitmapExtBlock)
FreeMem(BitmapExtBlock, SIZE * sizeof(unsigned long));
if (ZeroBlock)
FreeMem(ZeroBlock, SIZE * sizeof(unsigned long));
if (Io) {
if (Io->iotd_Req.io_Device) {
Io->iotd_Req.io_Command = CMD_UPDATE; /* ETD */
DoIO((struct IORequest *)Io);
Io->iotd_Req.io_Command = TD_MOTOR;
Io->iotd_Req.io_Length = 0;
DoIO((struct IORequest *)Io);
CloseDevice((struct IORequest *)Io);
}
DeleteExtIO((struct IORequest *)Io);
}
if (Port)
DeleteMsgPort(Port);
if (HandlerPort) {
DoPkt(HandlerPort, ACTION_INHIBIT, 0, 0, 0, 0, 0);
}
printf(
"Statistics: %d (%d) sectors (really) cleared,\n"
" %d (%d) tracks (really) deleted, \n"
" %d free sectors total.\n",
SectorsCleared,
SectorsReallyCleared,
TracksDeleted,
TracksReallyDeleted,
SectorsCleared + TracksDeleted * De.de_BlocksPerTrack);
}
int
main(int argc, char **argv)
{
char *colon;
int ac;
char **av;
if (DOSBase->dl_lib.lib_Version < 37) {
printf("Sorry, requires 2.04+ (V37+)\n");
return 20;
}
ac = argc - 1;
av = argv + 1;
while (ac > 0 && av[0][0] == '-') {
char *a = av[0] + 1;
while (a[0]) {
switch (a[0]) {
case 'n':
Pretend = 1;
printf("Pretend mode.\n");
break;
case 'v':
Verbose++;
break;
default:
goto usage;
}
a++;
}
ac--;
av++;
}
if (ac < 1) {
usage:
printf("Usage: %s [-n] [-v] devicename\n", argv[0]);
return 20;
}
if (colon = strchr(av[0], ':'))
*colon = '\0';
atexit(CloseAll);
if (OpenAll(av[0]) == 0) {
if (!Pretend) {
printf("Hit return to commence clearing %s: or CTRL-C to abort: ",
av[0]);
fflush(stdout);
while (!feof(stdin) && getchar() != '\n')
/* nothing */ ;
chkabort();
}
Clear();
}
/*CloseAll();*/
return 0;
}